package com.example.indenture.util;

import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import javax.net.ssl.SSLException;
public class FaceComparison {
     //将路径转化为base64编码
    private static String encodeImageToBase64(String imagePath) throws Exception {
        Path path = Paths.get(imagePath);
        byte[] imageBytes = Files.readAllBytes(path);
        return Base64.getEncoder().encodeToString(imageBytes);
    }
    // 获取API放回报告
    private static float checkConfidence(byte[] bacd) {//bacd是一个有效的JSON格式的字节数组
        //将字节数组转换为字符串
        String json = new String(bacd, StandardCharsets.UTF_8);
        //使用JSON库解析字符串，例如org.json
        JSONObject obj = new JSONObject(json);
        //检查是否有"confidence"参数，有：返回置信度，无：返回0
        return obj.has("confidence")?obj.getFloat("confidence"):0f;
    }
    // 人脸识别
    public float Recognize(String imageFilePath1,String imageFilePath2) throws Exception {
        // 设置API调用参数
        String url = "https://api-cn.faceplusplus.com/facepp/v3/compare";
        String apiKey = "FoEzPglLL6i8GrErz5fKbdHvA1yJ3weh";
        String apiSecret = "Qlz_r6zdTyGcSSYx9-sxMq-fxCt69hsF";
        // 存放请求参数参数
        HashMap<String, String> map = new HashMap<>();
        HashMap<String,String> byteMap = new HashMap<>();

        // 存入参数
        map.put("api_key", apiKey);  // 传入api_key
        map.put("api_secret", apiSecret); // 传入 api_secret
        map.put("image_base64_1", encodeImageToBase64(imageFilePath1)); // 传入图片1
        map.put("image_base64_2", encodeImageToBase64(imageFilePath2)); // 传入图片2
        map.put("return_landmark", "1");
        map.put("return_attributes", "gender,age,smiling,headpose,facequality,blur,eyestatus,emotion,ethnicity,beauty,mouthstatus,eyegaze,skinstatus");
        try{
            byte[] bacd = post(url, map, byteMap); // 发送post请求到第三方服务器
            return checkConfidence(bacd); // 返回结果
        }catch (Exception e) {
            e.printStackTrace();
        }
        return 0f;
    }


    private final static int CONNECT_TIME_OUT = 30000;
    private final static int READ_OUT_TIME = 50000;
    private static String boundaryString = getBoundary();
    protected static byte[] post(String url, HashMap<String, String> map, HashMap<String, String> fileMap) throws Exception {
        HttpURLConnection conne;
        URL url1 = new URL(url);
        conne = (HttpURLConnection) url1.openConnection();
        conne.setDoOutput(true);
        conne.setUseCaches(false);
        conne.setRequestMethod("POST");
        conne.setConnectTimeout(CONNECT_TIME_OUT);
        conne.setReadTimeout(READ_OUT_TIME);
        conne.setRequestProperty("accept", "*/*");
        conne.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundaryString);
        conne.setRequestProperty("connection", "Keep-Alive");
        conne.setRequestProperty("user-agent", "Mozilla/4.0 (compatible;MSIE 6.0;Windows NT 5.1;SV1)");
        DataOutputStream obos = new DataOutputStream(conne.getOutputStream());
        for (Map.Entry<String, String> entry : map.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            obos.writeBytes("--" + boundaryString + "\r\n");
            obos.writeBytes("Content-Disposition: form-data; name=\"" + key
                    + "\"\r\n");
            obos.writeBytes("\r\n");
            obos.writeBytes(value + "\r\n");
        }
        if(fileMap != null && fileMap.size() > 0){
            for (Map.Entry<String, String> fileEntry : fileMap.entrySet()) {
                obos.writeBytes("--" + boundaryString + "\r\n");
                obos.writeBytes("Content-Disposition: form-data; name=\"" + fileEntry.getKey()
                        + "\"; filename=\""  + "\"\r\n");
                obos.writeBytes("\r\n");
                obos.write(fileEntry.getValue().getBytes());
                obos.writeBytes("\r\n");
            }
        }
        obos.writeBytes("--" + boundaryString + "--" + "\r\n");
        obos.writeBytes("\r\n");
        obos.flush();
        obos.close();
        InputStream ins;
        int code = conne.getResponseCode();
        try{
            if(code == 200){
                ins = conne.getInputStream();
            }else{
                ins = conne.getErrorStream();
            }
        }catch (SSLException e){
            e.printStackTrace();
            return new byte[0];
        }
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buff = new byte[4096];
        int len;
        while((len = ins.read(buff)) != -1){
            baos.write(buff, 0, len);
        }
        byte[] bytes = baos.toByteArray();
        ins.close();
        return bytes;
    }
    private static String getBoundary() {
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for(int i = 0; i < 32; ++i) {
            sb.append("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-".charAt(random.nextInt("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_".length())));
        }
        return sb.toString();
    }
//    private static String encode() {
//        return URLEncoder.encode(" ", StandardCharsets.UTF_8);
//    }

    public static byte[] getBytesFromFile(File f) {
        if (f == null) {
            return null;
        }
        try {
            FileInputStream stream = new FileInputStream(f);
            ByteArrayOutputStream out = new ByteArrayOutputStream(1000);
            byte[] b = new byte[1000];
            int n;
            while ((n = stream.read(b)) != -1)
                out.write(b, 0, n);
            stream.close();
            out.close();
            return out.toByteArray();
        } catch (IOException e) {
        }
        return null;
    }
}